﻿using Engine;
using GameEntitySystem;
using TemplatesDatabase;

namespace Game
{
    public class ComponentCar : Component, IUpdateable
    {
        public SubsystemTime m_subsystemTime;

        public SubsystemAudio m_subsystemAudio;

        public ComponentMount m_componentMount;

        public ComponentBody m_componentBody;

        public ComponentDamage m_componentDamage;

        public ComponentPlayer componentPlayer;

        public float m_turnSpeed;

        public SubsystemTerrain m_subsystemTerrain;

        public double m_lastAutoJumpTime;

        public float m_jumpStrength;

        public bool isflying = false;

        public bool islanding = true;

        public float TurnOrder { get; set; }

        public float Health { get; set; }

        public UpdateOrder UpdateOrder => UpdateOrder.Default;

        public void Update(float dt)
        {
            bool flag = !m_componentBody.StandingOnValue.HasValue && m_componentBody.StandingOnBody == null;
            if (m_componentBody.ImmersionFactor <= 0f)
            {
                if (flag && !isflying)
                {
                    m_subsystemAudio.PlaySound("Audio/Flyup", 1f, 0f, m_componentBody.Position, 4f, autoDelay: true);
                    isflying = true;
                }
                else if (!flag && isflying)
                {
                    m_subsystemAudio.PlaySound("Audio/Down", 1f, 0f, m_componentBody.Position, 4f, autoDelay: true);
                    isflying = false;
                }

                if (m_subsystemTime.PeriodicGameTimeEvent(2.3, 0.0) && isflying)
                {
                    m_subsystemAudio.PlaySound("Audio/Flying", 1f, 0f, m_componentBody.Position, 4f, autoDelay: true);
                }

                BodyJump(dt);
            }
            else
            {
                if (m_componentDamage.Hitpoints - m_componentDamage.HitpointsChange >= 0.66f && m_componentBody.ImmersionFactor > 0f)
                {
                    m_subsystemAudio.PlaySound("Audio/Sinking", 0.1f, 0f, m_componentBody.Position, 4f, autoDelay: true);
                }

                BodyJump(dt);
            }

            TurnOrder = 0f;
        }

        public void BodyJump(float dt)
        {
            if (m_componentMount.Rider == null)
            {
                return;
            }

            ComponentPlayer componentPlayer = m_componentMount.Rider.Entity.FindComponent<ComponentPlayer>();
            if (componentPlayer == null)
            {
                return;
            }

            Vector3 viewDirection = componentPlayer.GameWidget.ActiveCamera.ViewDirection;
            bool flag = !m_componentBody.StandingOnValue.HasValue && m_componentBody.StandingOnBody == null;
            PlayerInput playerInput = componentPlayer.ComponentInput.PlayerInput;
            Vector2 vector = new Vector2(playerInput.Move.X, playerInput.Move.Z);
            Vector3 vector2 = new Vector3(0f, playerInput.Move.Y, 0f);
            float y = vector.Y;
            Vector3 velocity = m_componentBody.Velocity;
            Vector3 right = m_componentBody.Matrix.Right;
            Vector3 vector3 = Vector3.Transform(m_componentBody.Matrix.Forward, Quaternion.CreateFromAxisAngle(right, componentPlayer.ComponentLocomotion.LookAngles.Y));
            Vector3 vector4 = new Vector3(0f, 0f, 0f);
            vector4 += vector2;
            Vector3 vector5 = ((!SettingsManager.HorizontalCreativeFlight || componentPlayer == null || componentPlayer.ComponentInput.IsControlledByTouch) ? Vector3.Normalize(vector3 + 0.1f * Vector3.UnitY) : Vector3.Normalize(vector3 * new Vector3(1f, 0f, 1f)));
            Vector3 vector6 = 30f * (right * vector4.X + Vector3.UnitY * vector4.Y + vector5 * vector4.Z);
            float num = ((vector4 == Vector3.Zero) ? 5f : 3f);
            componentPlayer.ComponentLocomotion.LookOrder = new Vector2(playerInput.Look.X, playerInput.Look.Y);
            if (flag)
            {
                if (playerInput.Move.Y > 0f)
                {
                    Vector3 vector7 = vector4 * 10f;
                    m_componentBody.Velocity += dt * 30f * y * m_componentBody.Matrix.Forward + vector7;
                }
                else if (playerInput.Move.Y == 0f)
                {
                    m_componentBody.m_velocity.Y += 10f * dt;
                    m_componentBody.Velocity += dt * 30f * y * m_componentBody.Matrix.Forward + vector4;
                }
                else
                {
                    float num2 = MathUtils.Lerp(5f, 10f, MathUtils.Abs(vector4.Y));
                    m_componentBody.m_velocity.Y += 10f * dt;
                    m_componentBody.Velocity += dt * num2 * vector4;
                }
            }
            else
            {
                m_componentBody.Velocity += dt * 30f * y * m_componentBody.Matrix.Forward + vector4;
            }

            if (playerInput.VrMove.HasValue)
            {
                m_componentBody.ApplyDirectMove(playerInput.VrMove.Value);
            }

            TurnOrder = playerInput.Move.X;
            Quaternion rotation = m_componentBody.Rotation;
            float num3 = MathUtils.Atan2(2f * rotation.Y * rotation.W - 2f * rotation.X * rotation.Z, 1f - 2f * rotation.Y * rotation.Y - 2f * rotation.Z * rotation.Z);
            m_turnSpeed += 2.5f * m_subsystemTime.GameTimeDelta * (1f * TurnOrder - m_turnSpeed);
            num3 -= m_turnSpeed * dt * 4f;
            m_componentBody.Rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitY, num3);
        }

        public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
        {
            m_subsystemTime = base.Project.FindSubsystem<SubsystemTime>(throwOnError: true);
            m_subsystemAudio = base.Project.FindSubsystem<SubsystemAudio>(throwOnError: true);
            m_componentMount = base.Entity.FindComponent<ComponentMount>(throwOnError: true);
            m_componentBody = base.Entity.FindComponent<ComponentBody>(throwOnError: true);
            m_componentDamage = base.Entity.FindComponent<ComponentDamage>(throwOnError: true);
            m_subsystemTerrain = base.Project.FindSubsystem<SubsystemTerrain>(throwOnError: true);
            isflying = valuesDictionary.GetValue("isflying", defaultValue: false);
            islanding = valuesDictionary.GetValue("islanding", defaultValue: true);
        }

        public override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap)
        {
            valuesDictionary.SetValue("islanding", islanding);
            valuesDictionary.SetValue("isflying", isflying);
            base.Save(valuesDictionary, entityToIdMap);
        }
    }
}